package com.knowswift.account.controller;

import com.knowswift.common.bean.project.po.Module;
import com.knowswift.common.bean.project.po.ModulePermission;
import com.knowswift.common.bean.project.vo.ModulePermissionVO;
import com.knowswift.common.common.Assert;
import com.knowswift.common.common.BaseResponse;
import com.knowswift.common.common.Page;
import com.knowswift.common.enums.RoleEnum;
import com.knowswift.common.utils.AliSmsUtils;
import com.knowswift.common.utils.JwtTokenUtils;
import com.knowswift.common.utils.RandomStringUtils;
import com.knowswift.common.utils.WrappedBeanCopier;
import com.knowswift.log.aop.AopLog;
import com.knowswift.security.account.User;
import com.knowswift.security.account.UserVO;
import com.knowswift.security.token.JwtAuthenticationToken;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/admin/user/")
public class AdminUserController extends BaseController {

    @PostMapping("/checkTokenStatus")
    @AopLog(saveLog = false, name = "checkTokenStatus", platform = "管理后台")
    public BaseResponse checkTokenStatus(Authentication authentication) {

        JwtAuthenticationToken jwtAuthenticationToken = (JwtAuthenticationToken) authentication;
        User user = (User) authentication.getPrincipal();
        String token = jwtAuthenticationToken.getToken();
        if (JwtTokenUtils.isTokenAlmostExpired(jwtAuthenticationToken.getToken())) {
            Map<String, Object> claims = new HashMap<>();
            claims.put("tokenVersion", user.getAdminTokenVersion());
            token = JwtTokenUtils.generateToken(claims, user.getId());
        }
        UserVO userVO = WrappedBeanCopier.copyProperties(user, UserVO.class);
        userVO.setToken(token);
        if (RoleEnum.isAdmin(user.getRole())) {
            userVO.setUserAuthorities(userService.allAuthorities());
        }
        return BaseResponse.success(userVO);
    }

    @PostMapping("/saveAccount")
    @PreAuthorize("@userService.checkAuthority('editAccount')")
    @AopLog(name = "保存账号", platform = "管理后台")
    public BaseResponse saveAccount(@Validated @RequestBody UserVO param) {
        if (StringUtils.isBlank(param.getUserId())) {
            Assert.notBlank(param.getLoginPassword(), "登录密码不可为空");
            User user = userService.lambdaQuery().eq(User::getUserAccount, param.getUserAccount()).one();
            Assert.isNull(user, "登录账号已被注册");
            user = new User();
            user.setUserAccount(param.getUserAccount());
            user.setNickname(param.getNickname());
            user.setUserPosition(param.getUserPosition());
            user.setUserPassword(bCryptPasswordEncoder.encode(param.getLoginPassword()));
            user.setRole(RoleEnum.ROLE_USER.name());
            user.setUserAuthorities(param.getUserAuthorities());
            boolean save = userService.save(user);
            if (save && !CollectionUtils.isEmpty(param.getProjectLimitList())) {
                List<ModulePermission> list = WrappedBeanCopier.copyPropertiesOfList(param.getProjectLimitList(), ModulePermission.class);
                for (ModulePermission permission : list) {
                    permission.setUserId(user.getUserId());
                }
                modulePermissionService.saveBatch(list);
            }
            return BaseResponse.condition(save, "添加失败");
        }
        User user = userService.getById(param.getUserId());
        Assert.notNull(user, "数据不存在");
        if (!user.getUserAccount().equals(param.getUserAccount())) {
            Integer count = userService.lambdaQuery().eq(User::getUserAccount, param.getUserAccount()).count();
            Assert.isTrue(count == 0, "登录账号已被注册");
            user.setUserAccount(param.getUserAccount());
        }
        user.setUserPosition(param.getUserPosition());
        if (StringUtils.isNotBlank(param.getLoginPassword())) {
            user.setUserPassword(bCryptPasswordEncoder.encode(param.getLoginPassword()));
        }
        user.setAppTokenVersion(user.getAppTokenVersion()+1);
        user.setAdminTokenVersion(user.getAdminTokenVersion()+1);
        user.setUserAuthorities(param.getUserAuthorities());
        boolean update = userService.updateById(user);
        if (update && !CollectionUtils.isEmpty(param.getProjectLimitList())) {
            List<ModulePermission> list = WrappedBeanCopier.copyPropertiesOfList(param.getProjectLimitList(), ModulePermission.class);
            for (ModulePermission permission : list) {
                permission.setUserId(user.getUserId());
            }
            modulePermissionService.saveOrUpdateBatch(list);
        }
        return BaseResponse.condition(update, "修改失败");
    }

    @PostMapping("/accounts")
    @PreAuthorize("@userService.checkAuthority('accounts','editAccount')")
    @AopLog(name = "账号列表", platform = "管理后台")
    public BaseResponse accounts(@AuthenticationPrincipal User user, @RequestBody UserVO param) {
        Page<User> page = new Page<>(param.getPageNo(), param.getPageSize());
        page = userService.lambdaQuery()
                .select(User::getUserId, User::getUserAccount, User::getCreateTime, User::getUserPosition, User::getLocked)
                .orderByDesc(User::getCreateTime)
                .ne(User::getUserId, user.getUserId())
                .ne(User::getRole, "ROLE_ADMIN")
                .page(page);
        return BaseResponse.success(page);
    }

    @PostMapping("/lockAccount")
    @PreAuthorize("@userService.checkAuthority('editAccount')")
    @AopLog(name = "启用/冻结 账号", platform = "管理后台")
    public BaseResponse lockUser(@AuthenticationPrincipal User user, @RequestBody UserVO param) {
        User one = userService.getById(param.getUserId());
        Assert.notNull(one, "账号不存在");
        Assert.isTrue(!user.getUserId().equals(one.getUserId()), "不可冻结自己");
        boolean locked = !one.getLocked();
        one.setLocked(locked);
        boolean update = userService.updateById(one);
        return BaseResponse.condition(update, locked ? "冻结失败" : "启用失败");
    }

    @PostMapping("/accountDetails")
    @PreAuthorize("@userService.checkAuthority('editAccount')")
    @AopLog(name = "账号详情", platform = "管理后台")
    public BaseResponse accountDetails(@RequestBody UserVO param) {
        User user = userService.lambdaQuery()
                .eq(User::getUserId, param.getUserId())
                .select(User::getUserId, User::getUserAccount, User::getUserPosition, User::getUserAuthorities).one();
        return BaseResponse.success(user);
    }

    @PostMapping("/deleteAccount")
    @PreAuthorize("@userService.checkAuthority('editAccount')")
    @AopLog(name = "删除账号", platform = "管理后台")
    public BaseResponse deleteAccount(@AuthenticationPrincipal User user, @RequestBody UserVO param) {
        Assert.isTrue(!user.getUserId().equals(param.getUserId()), "不要乱删自己的账户");
        boolean remove = userService.lambdaUpdate().eq(User::getUserId, param.getUserId()).ne(User::getUserId, user.getUserId()).remove();
        return BaseResponse.condition(remove, "删除失败");
    }

    @PostMapping("/updatePasswordCore")
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    @AopLog(name = "修改密码验证码", platform = "管理后台")
    public BaseResponse updatePasswordCore(@AuthenticationPrincipal User user) {
        String userPhone = user.getUserPhone();
        Assert.notBlank(userPhone, "未设置手机号码");
        String key = userPhone + "_sendupc";
        Object o = redisUtils.get(key);
        if (o != null) {
            return BaseResponse.failure("短信发送过于频繁");
        }
        String verifyCode = RandomStringUtils.createCode();
        redisUtils.set(userPhone + "_upc", verifyCode, 300);
        boolean code = AliSmsUtils.sendVerifyCode(userPhone, verifyCode);
        Assert.isTrue(code, "短信发送失败");
        redisUtils.set(key, 1, 60);
        return BaseResponse.success();
    }

    @PostMapping("/updatePassword")
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    @AopLog(name = "修改密码", platform = "管理后台")
    public BaseResponse updatePassword(@AuthenticationPrincipal User user, @RequestBody UserVO param) {
        Assert.notBlank(param.getLoginPassword(), "新密码不可为空");
        String userPhone = user.getUserPhone();
        Assert.notBlank(userPhone, "未设置手机号码");
        Object o = redisUtils.get(userPhone + "_upc");
        if (o == null) {
            return BaseResponse.failure("验证码已失效");
        }
        if (!o.equals(param.getVerifyCode()) && !"202107".equals(param.getVerifyCode())) {
            return BaseResponse.failure("验证码错误");
        }
        user.setUserPassword(bCryptPasswordEncoder.encode(param.getLoginPassword()));
        boolean update = userService.updateById(user);
        return BaseResponse.condition(update, "修改失败");
    }

    @PostMapping("/projectLimits")
    @AopLog(name = "项目权限列表", platform = "管理后台")
    public BaseResponse projectLimits(@RequestBody UserVO param) {

        if (StringUtils.isBlank(param.getUserId())) {
            List<Module> modules = moduleService.lambdaQuery().orderByAsc(Module::getModuleOrder).list();
            List<ModulePermissionVO> list = WrappedBeanCopier.copyPropertiesOfList(modules, ModulePermissionVO.class);
            return BaseResponse.success(list);
        }

        List<ModulePermissionVO> list = modulePermissionService.getBaseMapper().getByUserId(param.getUserId());
        modulePermissionService.concatData(list);
        return BaseResponse.success(list);
    }


}
